package com.sky.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.crypto.digest.MD5;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.bo.EditPassWordBo;
import com.sky.bo.EmployeeAddBo;
import com.sky.bo.EmployeeBo;
import com.sky.bo.EmployeeEditBo;
import com.sky.constant.JwtClaimsConstant;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.EmployeeAddDto;
import com.sky.dto.EmployeeCheckDto;
import com.sky.dto.EmployeeEditDto;
import com.sky.dto.EmployeeLoginDTO;
import com.sky.entity.Employee;
import com.sky.exception.AccountLockedException;
import com.sky.exception.AccountNotFoundException;
import com.sky.exception.BaseException;
import com.sky.exception.PasswordErrorException;
import com.sky.mapper.EmployeeMapper;
import com.sky.properties.JwtProperties;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.EmployeeService;
import com.sky.utils.JwtUtil;
import com.sky.utils.admin.EmployeeUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Objects;

@Service
@Slf4j
public class EmployeeServiceImpl implements EmployeeService {

    @Autowired
    private EmployeeMapper employeeMapper;
    @Resource
    private EmployeeUtil employeeUtil;

    /**
     * 员工登录
     *
     * @param employeeLoginDTO
     * @return
     */
    public Employee login(EmployeeLoginDTO employeeLoginDTO) {
        String username = employeeLoginDTO.getUsername();
        //已经用注解进行判空 这里直接用MD5加密
        String password =DigestUtil.md5Hex(employeeLoginDTO.getPassword());

        //1、根据用户名查询数据库中的数据
        Employee employee = employeeMapper.getByUsername(username);

        //2、处理各种异常情况（用户名不存在、密码不对、账号被锁定）
        if (employee == null) {
            //账号不存在
            throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
        }


        //密码比对
        DigestUtil.md5Hex(employeeLoginDTO.getPassword());
        if (!password.equals(employee.getPassword())) {
            //密码错误
            throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
        }

        if (StatusConstant.DISABLE.equals(employee.getStatus())) {
            //账号被锁定
            throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);
        }

        //3、返回实体对象
        return employee;
    }

    //员工分页接口
    @Override
    public PageResult page(EmployeeBo employeeBo) {
        PageHelper.startPage(employeeBo.getPage(),employeeBo.getPageSize());
        Page<Employee> resultList = employeeMapper.pageList(employeeBo.getDTO());
        return PageResult.builder()
                .total(resultList.getTotal())
                .records(resultList.getResult())
                .build();
    }


    /**
     * 添加员工
     * @param employeeAddBo
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(EmployeeAddBo employeeAddBo, HttpServletRequest request) {
        EmployeeAddDto dto = employeeAddBo.getDto();
        //默认密码
        dto.setPassword(DigestUtil.md5Hex("123456"));
        dto.setStatus(StatusConstant.DISABLE);
        Employee employee = employeeMapper.checkRepeat(BeanUtil.copyProperties(dto, EmployeeCheckDto.class));
        if(employee != null) {
            if(employee.getIdNumber().equals(dto.getIdNumber())) {
                throw new BaseException("身份证已存在");
            }
            throw new BaseException("账号已存在");
        }
        String employeeName = employeeUtil.getEmployeeName(request);
        dto.setCreateUser(employeeName);
        dto.setUpdateUser(employeeName);
        employeeMapper.addEmployee(dto);
        return true;
    }

    /**
     * 根据id获取员工详情
     * @param id
     * @return
     */
    @Override
    public Employee getEmployeeById(Long id) {
        Employee employee = employeeMapper.getById(id);
        if (ObjectUtil.isEmpty(employee)) {
            throw new BaseException("没有查询到对应员工信息！");
        }
        return employee;
    }

    /**
     * 编辑员工
     * @param employeeEditBo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editEmployee(EmployeeEditBo employeeEditBo,HttpServletRequest request) {
        EmployeeEditDto dto = employeeEditBo.getDto();
        Employee employee = employeeMapper.checkRepeat(BeanUtil.copyProperties(dto, EmployeeCheckDto.class));
        //如果查出来有数据 并且不是自己的数据 则需要做校验
        if (employee != null) {
            if(dto.getIdNumber().equals(employee.getIdNumber())){
                throw new BaseException("身份证已存在");
            }
            if(dto.getUsername().equals(employee.getUsername())) {
                throw new BaseException("账号已存在");
            }
        }
        String employeeName = employeeUtil.getEmployeeName(request);
        dto.setUpdateUser(employeeName);
        Long result  = employeeMapper.editEmployee(dto);
        if(result>1||result==0){
            log.error("修改数量大于1或没有对应数据发生修改");
            throw new BaseException("修改失败");
        }
    }

    /**
     * 修改账号状态
     * @param status
     * @param id
     */
    @Override
    public void updateStatus(Integer status, Long id, HttpServletRequest request) {
        EmployeeEditDto dto = new EmployeeEditDto();
        dto.setStatus(status);
        dto.setId(id);
        dto.setUpdateUser(employeeUtil.getEmployeeName(request));
        Long result = employeeMapper.editEmployee(dto);
        if(result>1||result==0){
            log.error("修改数量大于1或没有对应数据发生修改");
            throw new BaseException("修改失败");
        }

    }

    /**
     * 修改密码
     * @param editPassWordBo
     * @param request
     */
    @Override
    public void editPassword(EditPassWordBo editPassWordBo, HttpServletRequest request) {
        Long employeeId = employeeUtil.getEmployeeId(request);
        if(employeeId == null) {
            throw new BaseException("没有获取到操作人信息！");
        }
        Employee employee = employeeMapper.getById(employeeId);
        if(ObjectUtil.isEmpty(employee)) {
            throw new BaseException("没有找到对应的用户！");
        }
        String oldPassword = DigestUtil.md5Hex(editPassWordBo.getOldPassword());
        String newPassword = DigestUtil.md5Hex(editPassWordBo.getNewPassword());
        if (!StrUtil.equals(employee.getPassword(),oldPassword)) {
            throw new BaseException("旧密码输入错误！");
        }
        //如果改的密码和原本密码一样 不需要更改
        if(StrUtil.equals(employee.getPassword(),newPassword)) {
            return;
        }
        employeeMapper.editEmployee(EmployeeEditDto.builder().
                id(employeeId).
                password(newPassword).
                build());
    }

}
